home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1997 #1 / Amiga Plus Extra 1997 #1.iso / programme / tools / leoutils / subtitle.c < prev    next >
C/C++ Source or Header  |  1996-11-16  |  21KB  |  795 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include <intuition/intuition.h>
  6. #include <utility/tagitem.h>
  7. #include <devices/inputevent.h>
  8. #include <graphics/rpattr.h>
  9.  
  10. #ifdef __SASC
  11. #include <proto/exec.h>
  12. #include <proto/dos.h>
  13. #include <proto/intuition.h>
  14. #include <proto/graphics.h>
  15. #include <proto/diskfont.h>
  16. #else
  17. #include <clib/dos_protos.h>
  18. #include <clib/exec_protos.h>
  19. #include <clib/intuition_protos.h>
  20. #include <clib/graphics_protos.h>
  21. #include <clib/diskfont_protos.h>
  22. #endif
  23.  
  24. #include "LeoLib.h"
  25.  
  26. #define VERSION "1.0"
  27.  
  28. #ifdef __SASC
  29. static char *Ver = "$VER:Subtitle " VERSION " " __AMIGADATE__ "©1996 Leopold-Soft";
  30. #else
  31. static char *Ver = "$VER:Subtitle " VERSION "© 1996 Leopold-Soft";
  32. #endif
  33.  
  34. #define MAX_LINES 6
  35. #define PREFERABLE_LINES 2
  36. #define MAX_LINE_LEN 256
  37.  
  38. #define RAW_ESC 69
  39. #define RAW_UP 76
  40. #define RAW_DOWN 77
  41. #define RAW_LEFT 79
  42. #define RAW_RIGHT 78
  43. #define RAW_SPACE 64
  44.  
  45. #define USE_WIDTH 600
  46. #define USE_HEIGHT_PAL 464
  47. #define USE_HEIGHT_NTSC 400
  48.  
  49. #define BLANK_TIME 10 /* In 1/50 s */
  50.  
  51. enum FmtCode {
  52.     fcPunct,
  53.     fcWord,
  54.     fcAny
  55. };
  56.  
  57. static struct Screen *scr[MAX_LINES] = {NULL};
  58. static struct Window *win[MAX_LINES] = {NULL};
  59. static struct IntuiMessage *IDCMP;
  60. static short emptyPens = ~0;
  61. static BOOL quit = FALSE;
  62.  
  63. static ULONG GetTicks(void);
  64. static int Cut(const UBYTE *s, int max, enum FmtCode fmtCode);
  65. static int FormatText(char dstLines[MAX_LINES][MAX_LINE_LEN],
  66.                 const char srcLines[MAX_LINES][MAX_LINE_LEN],
  67.                 int nOfSrcL, enum FmtCode fmtCode);
  68.  
  69. static FILE *fp = NULL;
  70.  
  71. static struct TextExtent extent;
  72.  
  73. static char fontName[31]="CGTriumvirate";
  74. static int Heights[MAX_LINES];
  75. static UWORD __chip windowPointer[6] = {0, 0, 0, 0, 0, 0};
  76.  
  77. static struct TextAttr fontTextAttr = {
  78.     (STRPTR)fontName,
  79.                 /* ta_Name */
  80.     39,            /* ta_YSize */
  81.     FS_NORMAL,    /* ta_Style */
  82.     0x0            /* ta_Flags e.g. FSB_BOLD */
  83. };
  84.  
  85. static struct TextFont *font[2] = {NULL, NULL};
  86.  
  87. static char lines[MAX_LINES][MAX_LINE_LEN], tmpLines[MAX_LINES][MAX_LINE_LEN];
  88. static int xOffset;
  89.  
  90. struct Render {
  91.     int x, y, pen; /* when pen = -1, quit */
  92. };
  93.  
  94. static const struct Render coords[] = {
  95.     /* Immediate outline ±2 pixels in every direction */
  96.     {-2,  0,  1},
  97.     {-1,  1,  1},
  98.     { 0,  2,  1},
  99.     { 1,  1,  1},
  100.     { 2,  0,  1},
  101.     { 1, -1,  1},
  102.     { 0, -2,  1},
  103.     {-1, -1,  1},
  104.  
  105.     /* Shadow to the right upto +4 pixels */
  106.     { 2,  2,  1},
  107.     { 3,  1,  1},
  108.     { 4,  0,  1},
  109.     { 3, -1,  1},
  110.     { 2, -2,  1},
  111.  
  112.     /* Shadow to the right upto +6 pixels */
  113.     { 4,  2,  1},
  114.     { 5,  1,  1},
  115.     { 6,  0,  1},
  116.     { 5, -1,  1},
  117.     { 4, -2,  1},
  118.  
  119.     /* Grey outline ±1 pixel in every direction */
  120.     { 0, -1,  2},
  121.     { 0,  1,  2},
  122.     {-1,  0,  2},
  123.     { 1,  0,  2},
  124.  
  125.     /* The text itself */
  126.     { 0,  0,  3},
  127.  
  128.     /* End tag */
  129.     { 0,  0, -1}
  130. };
  131.  
  132.  
  133.  
  134. /* Main program. Should perhaps later be able to do italics */
  135.  
  136. int main(int argc, char **argv) {
  137.     int i, j, offset = (argc > 1 && !strcmp(argv[1], "-f")) ? 1 : 0;
  138.     int error = EXIT_FAILURE;
  139.     int useHeight;
  140.  
  141.     if (argc < 2 || argc > 4+offset) {
  142.         printf(    "Subtitle v" VERSION " ©1996 Leopold-Soft / Henrik Herranen\n"
  143.                 "e-mail: leopold@cs.tut.fi\n"
  144.                 "URL: http://www.cs.tut.fi/~leopold/\n"
  145.                 "\nUsage: %s [-f] FileName [FontName [FontSize]]\n"
  146.                 "Defaults: FontName=%s, FontSize=%d\n"
  147.                 ,argv[0], fontName, fontTextAttr.ta_YSize);
  148.         return EXIT_SUCCESS;
  149.     }
  150.  
  151.     if (!(fp = fopen(argv[1+offset], "r"))) {
  152.         printf("*** ERROR: Couldn't open file %s for reading\n", argv[1+offset]);
  153.         goto cleanup;
  154.     }
  155.  
  156.     if (argc > 3+offset) {
  157.         i = atoi(argv[3+offset]);
  158.         if (i < 8) {
  159.             printf("Illegal font size %s, defaulting to 8\n", argv[3+offset]);
  160.             i = 8;
  161.         }
  162.         fontTextAttr.ta_YSize = i;
  163.     } else {
  164.         i = fontTextAttr.ta_YSize;
  165.     }
  166.  
  167.     if (argc > 2+offset) {
  168.         strncpy(fontTextAttr.ta_Name, argv[2+offset], 25);
  169.         fontTextAttr.ta_Name[25] = '\0';
  170.     }
  171.     strcat(fontTextAttr.ta_Name, ".font");
  172.     if (!(font[0] = OpenDiskFont(&fontTextAttr))) {
  173.         printf("*** ERROR: Couldn't open %s %d\n",
  174.             fontTextAttr.ta_Name, fontTextAttr.ta_YSize);
  175.         goto cleanup;
  176.     }
  177.     if (font[0]->tf_YSize != i)
  178.         printf("Warning: Asked for font size %d (normal), but got %d\n",
  179.         i, font[0]->tf_YSize);
  180.  
  181.     fontTextAttr.ta_Style = FSF_ITALIC;
  182.     if (!(font[1] = OpenDiskFont(&fontTextAttr))) {
  183.         printf("*** ERROR: Couldn't open %s %d\n",
  184.             fontTextAttr.ta_Name, fontTextAttr.ta_YSize);
  185.         goto cleanup;
  186.     }
  187.     if (font[1]->tf_YSize != i)
  188.         printf("Warning: Asked for font size %d (italic), but got %d\n",
  189.         i, font[1]->tf_YSize);
  190.  
  191.     for (i=0; i<4; i++) {
  192.         if (!(scr[i] = OpenScreenTags(NULL,
  193.                     SA_Depth, 2,
  194.                     SA_Title, "Subtitle " VERSION " by Leopold-Soft",
  195.                     SA_Overscan, OSCAN_TEXT,
  196.                     SA_SysFont, 1,
  197.                     SA_DisplayID, HIRESLACE_KEY,
  198.                     SA_Pens, &emptyPens,
  199.                     SA_Quiet, TRUE,
  200.                     SA_ShowTitle, FALSE,
  201.                     TAG_END))) {
  202.             printf("*** ERROR: Couldn't open screen! Perhaps low on memory?\n");
  203.             goto cleanup;
  204.         }
  205.         SetRGB4(&scr[i]->ViewPort, 0, 8,10, 8);
  206.         SetRGB4(&scr[i]->ViewPort, 1, 0, 0, 0);
  207.         SetRGB4(&scr[i]->ViewPort, 2, 7, 7, 7);
  208.         SetRGB4(&scr[i]->ViewPort, 3,15,15,15);
  209.  
  210.         if (!(win[i] = OpenWindowTags(NULL,
  211.                     WA_IDCMP, IDCMP_RAWKEY,
  212.                     WA_CustomScreen, scr[i],
  213.                     WA_Activate, TRUE,
  214.                     WA_NoCareRefresh, TRUE,
  215.                     WA_WBenchWindow, FALSE,
  216.                     WA_ScreenTitle, "Subtitle " VERSION " by Leopold-Soft",
  217.                     WA_Backdrop, TRUE,
  218.                     WA_Borderless, TRUE,
  219.                     TAG_END))) {
  220.             printf("*** ERROR: Couldn't open window!\n");
  221.             goto cleanup;
  222.         }
  223.         SetPointer(win[i], windowPointer, 1, 16, -1, -1);
  224.  
  225.         SetRPAttrs(win[i]->RPort,
  226.             RPTAG_Font, font[0],
  227.             RPTAG_APen, 1,
  228.             RPTAG_DrMd, JAM1,
  229.             TAG_END);
  230.     }
  231.  
  232.     useHeight = (scr[0]->Height >= 512) ? USE_HEIGHT_PAL : USE_HEIGHT_NTSC;
  233.     if (scr[0]->Height < useHeight) {
  234.         printf("*** ERROR: System vertical overscan only %d pixels, "
  235.                 "while %d required!\n", scr[0]->Height, useHeight);
  236.         goto cleanup;
  237.     }
  238.     Heights[0] = win[0]->Height - (win[0]->Height - useHeight)/2 -
  239.                     font[0]->tf_YSize + font[0]->tf_Baseline;
  240.     for (i=1; i<MAX_LINES; i++)
  241.         Heights[i] = Heights[i-1] - font[0]->tf_YSize;
  242.     xOffset = (win[0]->Width - USE_WIDTH)/2;
  243.  
  244.     Move(win[2]->RPort, (long)xOffset, 100);
  245.     Text(win[2]->RPort, "Subtitle " VERSION " ©1996 Leopold-Soft    ", 32);
  246.     Move(win[2]->RPort, (long)xOffset, 200);
  247.     Text(win[2]->RPort, "Press -> (Cursor right)", 23);
  248.     ScreenToFront(scr[2]);
  249.  
  250.     while (!quit) {
  251.         static int cw = -1;
  252.         ULONG now;
  253.         static BOOL blankInFront = FALSE;
  254.         int l;
  255.         cw++;
  256.         cw &= 3;
  257.         if (!cw)
  258.             Delay(1);
  259.         while (IDCMP = (struct IntuiMessage *) GetMsg(win[cw] -> UserPort)) {
  260.             int code = IDCMP->Code;
  261.             int class = IDCMP->Class;
  262.             struct Window *tmpWin;
  263.             ReplyMsg((APTR) IDCMP);
  264.  
  265.             if (class & IDCMP_RAWKEY) {
  266.                 switch (code) {
  267.                 case RAW_ESC + IECODE_UP_PREFIX:
  268.                     quit = TRUE;
  269.                     error = EXIT_SUCCESS;
  270.                     break;
  271.                 case RAW_SPACE:
  272.                     ScreenToFront(scr[3]);
  273.                     blankInFront = TRUE;
  274.                     break;
  275.                 case RAW_UP:
  276.                 case RAW_DOWN:
  277.                     ScreenToFront(scr[3]);
  278.                     now = GetTicks();
  279.                     if (!blankInFront)
  280.                         while (GetTicks() < now + BLANK_TIME);
  281.                     blankInFront = FALSE;
  282.                     ScreenToFront(win[1]->WScreen);
  283.                     break;
  284.                 case RAW_LEFT:
  285.                     ScreenToFront(scr[3]);
  286.                     now = GetTicks();
  287.                     if (!blankInFront)
  288.                         while (GetTicks() < now + BLANK_TIME);
  289.                     blankInFront = FALSE;
  290.                     ScreenToFront(win[2]->WScreen);
  291.                     break;
  292.                 case RAW_RIGHT:
  293.                     ScreenToFront(scr[3]);
  294.                     now = GetTicks();
  295.                     if (!blankInFront)
  296.                         while (GetTicks() < now + BLANK_TIME);
  297.                     blankInFront = FALSE;
  298.                     ScreenToFront(win[0]->WScreen);
  299.                     for (i=0; i<MAX_LINES; i++)
  300.                         lines[0][i] = tmpLines[0][i] = '\0';
  301.                     tmpWin = win[2];
  302.                     win[2] = win[1];
  303.                     win[1] = win[0];
  304.                     win[0] = tmpWin;
  305.                     j = 0;
  306.                     /* Read the input lines to be processed */
  307.                     do {
  308.                         int pos=0, c;
  309.                         while((c = fgetc(fp)) != '\n' && c != EOF && pos < MAX_LINE_LEN-1)
  310.                             tmpLines[j][pos++] = c;
  311.                         tmpLines[j][pos] = '\0';
  312.                     } while (strlen(tmpLines[j]) && ++j < MAX_LINES);
  313.  
  314.                     if (j >= MAX_LINES) {
  315.                         printf("*** ERROR: Too many consecutive source lines, read up to:\n");
  316.                         for (i=0; i<MAX_LINES; i++)
  317.                             printf("> %s\n", tmpLines[i]);
  318.                         goto cleanup;
  319.                     }
  320.  
  321.                     if (j && !strcmp(tmpLines[0], "#i")) {
  322.                         j--;
  323.                         SetRPAttrs(win[0]->RPort,
  324.                             RPTAG_Font, font[1],
  325.                             TAG_END);
  326.                         for (i=0; i<j; i++)
  327.                             strcpy(tmpLines[i], tmpLines[i+1]);
  328.                         tmpLines[j][0] = '\0';
  329.                     }
  330.                     /* j holds the number of src lines */
  331.                     l = FormatText(lines, tmpLines, j, fcPunct);
  332.                     if (l > PREFERABLE_LINES) {
  333.                         int newL = FormatText(lines, tmpLines, j, fcWord);
  334.                         if (newL > PREFERABLE_LINES) {
  335.                             int newestL = FormatText(lines, tmpLines, j, offset ? fcWord : fcAny);
  336.                             if (newestL > MAX_LINES) {
  337.                                 printf("*** ERROR: Cant fit following text in %d lines:\n",
  338.                                     MAX_LINES);
  339.                                 for (i=0; i<j; i++)
  340.                                     printf("> %s\n", tmpLines[i]);
  341.                                     goto cleanup;
  342.                             } else if (newestL == l) {
  343.                                 l = FormatText(lines, tmpLines, j, fcPunct);
  344.                             } else if (newestL == newL) {
  345.                                 l = FormatText(lines, tmpLines, j, fcWord);
  346.                             } else {
  347.                                 l = newestL;
  348.                             }
  349.                         } else if (newL == l) {
  350.                             l = FormatText(lines, tmpLines, j, fcPunct);
  351.                         } else {
  352.                             l = newL;
  353.                         }
  354.                     }
  355.  
  356. /*                    for (i=0; i<MAX_LINES; i++)
  357.                         printf("print line %d = %s\n", i, lines[i]);
  358. */
  359.                     if (l) {
  360.                         static char t[MAX_LINE_LEN];
  361.                         for (i=0; i<l>>1; i++) {
  362.                             strcpy(t, lines[i]);
  363.                             strcpy(lines[i], lines[l-i-1]);
  364.                             strcpy(lines[l-i-1], t);
  365.                         }
  366.                     }
  367.  
  368.                     SetRPAttrs(win[0]->RPort, RPTAG_APen, 0, TAG_END);
  369.                     BltPattern(win[0]->RPort, NULL, 0, 0,
  370.                         (long)win[0]->Width, (long)win[0]->Height, 0);
  371.                     for (i=0; i<MAX_LINES; i++) {
  372.                         int len = strlen(lines[i]);
  373. /*                        printf("print line %d = %s\n", i, lines[i]);*/
  374.                         if (len) {
  375.                             j = 0;
  376.                             while(coords[j].pen != -1) {
  377.                                 SetRPAttrs(win[0]->RPort, RPTAG_APen,
  378.                                     coords[j].pen, TAG_END);
  379.                                 Move(win[0]->RPort, (long)xOffset + coords[j].x,
  380.                                     (long)Heights[i] + coords[j].y);
  381.                                 Text(win[0]->RPort, lines[i], (ULONG)len);
  382.                                 j++;
  383.                             }
  384.                         }
  385.                     }
  386.                     SetRPAttrs(win[0]->RPort,
  387.                         RPTAG_Font, font[0],
  388.                         TAG_END);
  389.                     break;
  390.                 }
  391.             }
  392.         }
  393.     }
  394.  
  395.     ScreenToFront(scr[3]);
  396.     error = EXIT_SUCCESS;
  397.  
  398. cleanup:
  399.     for (i=0; i<4; i++)
  400.         if (win[i]) {
  401.             ClearPointer(win[i]);
  402.             CloseWindow(win[i]);
  403.         }
  404.     for (i=0; i<4; i++)
  405.         if (scr[i])
  406.             CloseScreen(scr[i]);
  407.     if (font[1])
  408.         CloseFont(font[1]);
  409.     if (font[0])
  410.         CloseFont(font[0]);
  411.     if (fp)
  412.         fclose(fp);
  413.  
  414.     return error;
  415. }
  416.  
  417. /*******************************************************\
  418. *                                                        *
  419. *    GetTicks()                                            *
  420. *                                                        *
  421. *    Returns the current time in fiftieth of seconds        *
  422. *                                                        *
  423. \*******************************************************/
  424.  
  425. static ULONG GetTicks(void) {
  426.     static struct DateStamp ds;
  427.     DateStamp(&ds);
  428.     return (ULONG) (ds.ds_Tick + (ds.ds_Minute + ds.ds_Days*24*60)*60*TICKS_PER_SECOND);
  429. }
  430.  
  431. #define CF 2    /* Consonant */
  432. #define VF 1    /* Vowel */
  433. #define PF 4    /* Punctuation */
  434.  
  435. static const UBYTE charTab[257] = {
  436.         0, /* $-1  -1    */
  437.         0, /* $ 0   0    */
  438.         0, /* $ 1   1    */
  439.         0, /* $ 2   2    */
  440.         0, /* $ 3   3    */
  441.         0, /* $ 4   4    */
  442.         0, /* $ 5   5    */
  443.         0, /* $ 6   6    */
  444.         0, /* $ 7   7    */
  445.         0, /* $ 8   8    */
  446.         0, /* $ 9   9    */
  447.         0, /* $ A  10    */
  448.         0, /* $ B  11    */
  449.         0, /* $ C  12    */
  450.         0, /* $ D  13    */
  451.         0, /* $ E  14    */
  452.         0, /* $ F  15    */
  453.         0, /* $10  16    */
  454.         0, /* $11  17    */
  455.         0, /* $12  18    */
  456.         0, /* $13  19    */
  457.         0, /* $14  20    */
  458.         0, /* $15  21    */
  459.         0, /* $16  22    */
  460.         0, /* $17  23    */
  461.         0, /* $18  24    */
  462.         0, /* $19  25    */
  463.         0, /* $1A  26    */
  464.         0, /* $1B  27    */
  465.         0, /* $1C  28    */
  466.         0, /* $1D  29    */
  467.         0, /* $1E  30    */
  468.         0, /* $1F  31    */
  469.         0, /* $20  32    */
  470.  PF         , /* $21  33 !  */
  471.         0, /* $22  34 "  */
  472.         0, /* $23  35 #  */
  473.         0, /* $24  36 $  */
  474.         0, /* $25  37 %  */
  475.         0, /* $26  38 &  */
  476.         0, /* $27  39 '  */
  477.         0, /* $28  40 (  */
  478.         0, /* $29  41 )  */
  479.         0, /* $2A  42 *  */
  480.         0, /* $2B  43 +  */
  481.  PF         , /* $2C  44 ,  */
  482.         0, /* $2D  45 -  */
  483.  PF         , /* $2E  46 .  */
  484.         0, /* $2F  47 /  */
  485.         0, /* $30  48 0  */
  486.         0, /* $31  49 1  */
  487.         0, /* $32  50 2  */
  488.         0, /* $33  51 3  */
  489.         0, /* $34  52 4  */
  490.         0, /* $35  53 5  */
  491.         0, /* $36  54 6  */
  492.         0, /* $37  55 7  */
  493.         0, /* $38  56 8  */
  494.         0, /* $39  57 9  */
  495.  PF         , /* $3A  58 :  */
  496.  PF         , /* $3B  59 ;  */
  497.         0, /* $3C  60 <  */
  498.         0, /* $3D  61 =  */
  499.         0, /* $3E  62 >  */
  500.  PF         , /* $3F  63 ?  */
  501.         0, /* $40  64 @  */
  502.        VF, /* $41  65 A  */
  503.     CF   , /* $42  66 B  */
  504.     CF   , /* $43  67 C  */
  505.     CF   , /* $44  68 D  */
  506.        VF, /* $45  69 E  */
  507.     CF   , /* $46  70 F  */
  508.     CF   , /* $47  71 G  */
  509.     CF   , /* $48  72 H  */
  510.        VF, /* $49  73 I  */
  511.     CF   , /* $4A  74 J  */
  512.     CF   , /* $4B  75 K  */
  513.     CF   , /* $4C  76 L  */
  514.     CF   , /* $4D  77 M  */
  515.     CF   , /* $4E  78 N  */
  516.        VF, /* $4F  79 O  */
  517.     CF   , /* $50  80 P  */
  518.     CF   , /* $51  81 Q  */
  519.     CF   , /* $52  82 R  */
  520.     CF   , /* $53  83 S  */
  521.     CF   , /* $54  84 T  */
  522.        VF, /* $55  85 U  */
  523.     CF   , /* $56  86 V  */
  524.     CF   , /* $57  87 W  */
  525.     CF   , /* $58  88 X  */
  526.        VF, /* $59  89 Y  */
  527.     CF   , /* $5A  90 Z  */
  528.         0, /* $5B  91 [  */
  529.         0, /* $5C  92 \  */
  530.         0, /* $5D  93 ]  */
  531.         0, /* $5E  94 ^  */
  532.         0, /* $5F  95 _  */
  533.         0, /* $60  96 `  */
  534.        VF, /* $61  97 a  */
  535.     CF   , /* $62  98 b  */
  536.     CF   , /* $63  99 c  */
  537.     CF   , /* $64 100 d  */
  538.        VF, /* $65 101 e  */
  539.     CF   , /* $66 102 f  */
  540.     CF   , /* $67 103 g  */
  541.     CF   , /* $68 104 h  */
  542.        VF, /* $69 105 i  */
  543.     CF   , /* $6A 106 j  */
  544.     CF   , /* $6B 107 k  */
  545.     CF   , /* $6C 108 l  */
  546.     CF   , /* $6D 109 m  */
  547.     CF   , /* $6E 110 n  */
  548.        VF, /* $6F 111 o  */
  549.     CF   , /* $70 112 p  */
  550.     CF   , /* $71 113 q  */
  551.     CF   , /* $72 114 r  */
  552.     CF   , /* $73 115 s  */
  553.     CF   , /* $74 116 t  */
  554.        VF, /* $75 117 u  */
  555.     CF   , /* $76 118 v  */
  556.     CF   , /* $77 119 w  */
  557.     CF   , /* $78 120 x  */
  558.        VF, /* $79 121 y  */
  559.     CF   , /* $7A 122 z  */
  560.         0, /* $7B 123 {  */
  561.         0, /* $7C 124 |  */
  562.         0, /* $7D 125 }  */
  563.         0, /* $7E 126 ~  */
  564.         0, /* $7F 127    */
  565.         0, /* $80 128    */
  566.         0, /* $81 129    */
  567.         0, /* $82 130    */
  568.         0, /* $83 131    */
  569.         0, /* $84 132    */
  570.         0, /* $85 133    */
  571.         0, /* $86 134    */
  572.         0, /* $87 135    */
  573.         0, /* $88 136    */
  574.         0, /* $89 137    */
  575.         0, /* $8A 138    */
  576.         0, /* $8B 139    */
  577.         0, /* $8C 140    */
  578.         0, /* $8D 141    */
  579.         0, /* $8E 142    */
  580.         0, /* $8F 143    */
  581.         0, /* $90 144    */
  582.         0, /* $91 145    */
  583.         0, /* $92 146    */
  584.         0, /* $93 147    */
  585.         0, /* $94 148    */
  586.         0, /* $95 149    */
  587.         0, /* $96 150    */
  588.         0, /* $97 151    */
  589.         0, /* $98 152    */
  590.         0, /* $99 153    */
  591.         0, /* $9A 154    */
  592.         0, /* $9B 155    */
  593.         0, /* $9C 156    */
  594.         0, /* $9D 157    */
  595.         0, /* $9E 158    */
  596.         0, /* $9F 159    */
  597.         0, /* $A0 160 hard space        */
  598.  PF         , /* $A1 161 ! upside down        */
  599.         0, /* $A2 162 cent                */
  600.         0, /* $A3 163 pound             */
  601.         0, /* $A4 164 equ sun             */
  602.         0, /* $A5 165 yen                */
  603.         0, /* $A6 166 double pipe        */
  604.         0, /* $A7 167 rule (SS)            */
  605.         0, /* $A8 168 Umlaut "            */
  606.         0, /* $A9 169 (C)                */
  607.         0, /* $AA 170 a over -            */
  608.         0, /* $AB 171 <<                */
  609.         0, /* $AC 172 overscore (-) w/ hook    */
  610.         0, /* $AD 173 strikethru (-)    */
  611.         0, /* $AE 174 (R)                */
  612.         0, /* $AF 175 overscore (-)        */
  613.         0, /* $B0 176 degree            */
  614.         0, /* $B1 177 +-                */
  615.         0, /* $B2 178 ^2                */
  616.         0, /* $B3 179 ^3                */
  617.         0, /* $B4 180 single umlaut '    */
  618.         0, /* $B5 181 micro, u            */
  619.         0, /* $B6 182 pi                */
  620.         0, /* $B7 183 dot                */
  621.         0, /* $B8 184 accent ,            */
  622.         0, /* $B9 185 ^1                */
  623.         0, /* $BA 186 o over -            */
  624.         0, /* $BB 187 >>                */
  625.         0, /* $BC 188 1/4                */
  626.         0, /* $BD 189 1/2                */
  627.         0, /* $BE 190 3/4                */
  628.  PF         , /* $BF 191 ? upside down        */
  629.        VF, /* $C0 192 A` */
  630.        VF, /* $C1 193 A' */
  631.        VF, /* $C2 194 A^ */
  632.        VF, /* $C3 195 A~ */
  633.        VF, /* $C4 196 A" */
  634.        VF, /* $C5 197 Ao */
  635.        VF, /* $C6 198 AE */
  636.     CF   , /* $C7 199 C, */
  637.        VF, /* $C8 200 E` */
  638.        VF, /* $C9 201 E' */
  639.        VF, /* $CA 202 E^ */
  640.        VF, /* $CB 203 E" */
  641.        VF, /* $CC 204 I` */
  642.        VF, /* $CD 205 I' */
  643.        VF, /* $CE 206 I^ */
  644.        VF, /* $CF 207 I" */
  645.     CF   , /* $D0 208 -D */
  646.     CF   , /* $D1 209 N~ */
  647.        VF, /* $D2 210 O` */
  648.        VF, /* $D3 211 O' */
  649.        VF, /* $D4 212 O^ */
  650.        VF, /* $D5 213 O~ */
  651.        VF, /* $D6 214 O" */
  652.         0, /* $D7 215 ×  */
  653.        VF, /* $D8 216 O/ */
  654.        VF, /* $D9 217 U` */
  655.        VF, /* $DA 218 U' */
  656.        VF, /* $DB 219 U^ */
  657.        VF, /* $DC 220 U" */
  658.        VF, /* $DD 221 Y' */
  659.        VF, /* $DE 222 |O */
  660.     CF   , /* $DF 223 |B */
  661.        VF, /* $E0 224 a` */
  662.        VF, /* $E1 225 a' */
  663.        VF, /* $E2 226 a^ */
  664.        VF, /* $E3 227 a~ */
  665.        VF, /* $E4 228 a" */
  666.        VF, /* $E5 229 ao */
  667.        VF, /* $E6 230 ae */
  668.     CF   , /* $E7 231 c, */
  669.        VF, /* $E8 232 e` */
  670.        VF, /* $E9 233 e' */
  671.        VF, /* $EA 234 e^ */
  672.        VF, /* $EB 235 e" */
  673.        VF, /* $EC 236 i` */
  674.        VF, /* $ED 237 i' */
  675.        VF, /* $EE 238 i^ */
  676.        VF, /* $EF 239 i" */
  677.     CF   , /* $F0 240 d- */
  678.     CF   , /* $F1 241 n~ */
  679.        VF, /* $F2 242 o` */
  680.        VF, /* $F3 243 o' */
  681.        VF, /* $F4 244 o^ */
  682.        VF, /* $F5 245 o~ */
  683.        VF, /* $F6 246 o" */
  684.         0, /* $F7 247 '-.*/
  685.        VF, /* $F8 248 o/ */
  686.        VF, /* $F9 249 u` */
  687.        VF, /* $FA 250 u' */
  688.        VF, /* $FB 251 u^ */
  689.        VF, /* $FC 252 u" */
  690.        VF, /* $FD 253 y' */
  691.        VF, /* $FE 254 |o */
  692.        VF  /* $FF 255 y" */
  693. };
  694.  
  695.  
  696. static int type(int d) {
  697.     return charTab[d+1]&(CF|VF);
  698. }
  699.  
  700. static const int state[3][3] = {
  701.     { 0, 1,   0 },
  702.     { 2, 1,   0 },
  703.     { 2, 1+4, 0 }
  704. };
  705.  
  706. /*
  707.     Returns the length of the longest possible substring in the source string,
  708.     according to the given constraints:
  709.         s = string
  710.         max = maximum number of characters to be examined
  711.         fmtCode = format code: where lines can change
  712. */
  713. static int Cut(const UBYTE *s, int max, enum FmtCode fmtCode) {
  714.     int pos = 0, top = 16384, cc, r;
  715.     if (fmtCode == fcAny) {
  716.         int p = 0;
  717.         while ((cc = s[pos]) != '\0' && pos <= max) {
  718.             p = state[p][2-type(cc)];
  719.             if (p & 4) {        /* Handle possible flag in table */
  720.                 p &= ~4;
  721.                 if (!(pos >= 3 && IsSpace(s[pos-3])))
  722.                     top = 32768 + pos - 1;
  723.             }
  724.             pos++;
  725.             if (IsSpace(cc) && !(s[pos] == '-' && s[pos+1] == '\0') &&
  726.                     !(pos >= 2 && s[pos-1] == '-' && IsSpace(s[pos-2])))
  727.                 top = pos;
  728.         }
  729.     } else if (fmtCode == fcWord) {
  730.         while ((cc = s[pos]) != '\0' && pos++ < max)
  731.             if (IsSpace(cc) && !(s[pos] == '-' && s[pos+1] == '\0') &&
  732.                     !(pos >= 2 && s[pos-1] == '-' && IsSpace(s[pos-2])))
  733.                 top = pos;
  734.     } else {
  735.         while ((cc = s[pos]) != '\0' && pos++ < max)
  736.             if ((charTab[cc+1] & PF) && IsSpace(s[pos]) && pos < max &&
  737.                                 !(s[pos] == '-' && s[pos+1] == '\0') &&
  738.                     !(pos >= 2 && s[pos-1] == '-' && IsSpace(s[pos-2])))
  739.                 top = pos+1;
  740.     }
  741.     r = (cc == '\0' && pos <= max) ? pos : top;
  742. /*    printf("Cut: fmtCode = %d, pos = %d, max = %d, r=%d\n%s\n", fmtCode, pos, max, r, s);
  743.     for (pos=0; pos<(r&~(32768|16384))-1; pos++)
  744.         printf(" ");
  745.     printf("^last\n");*/
  746.     return r;
  747. }
  748.  
  749.  
  750.  
  751. /* Formats text to the given destination from a given source */
  752. static int FormatText(char dstLines[MAX_LINES][MAX_LINE_LEN],
  753.                 const char srcLines[MAX_LINES][MAX_LINE_LEN],
  754.                 int nOfSrcL, enum FmtCode fmtCode) {
  755.     int nOfDstL = 0, i, srcL=0;
  756.     for (i=0; i<MAX_LINES; i++)
  757.         dstLines[i][0] = '\0';
  758. /*    printf("FormatText: fmtCode = %d\n", fmtCode);*/
  759.  
  760.     while(srcL < nOfSrcL) {
  761.         int pos = 0, srcLLen = strlen(srcLines[srcL]);
  762. /*        printf("srcLLen = %d, l=\"%s\"\n", srcLLen, srcLines[srcL]);*/
  763.         while(pos < srcLLen) {
  764.             BOOL broken = FALSE;
  765.             int width;
  766. /*            printf("srcL=%d, nOfSrcL=%d, pos=%d, srcLLen = %d\n",
  767.                 srcL, nOfSrcL, pos, srcLLen);*/
  768.             width = TextFit(win[0]->RPort, (char *)srcLines[srcL]+pos,
  769.                 (ULONG)strlen(srcLines[srcL]+pos),
  770.                 &extent, NULL, 1, USE_WIDTH, 32767);
  771.             width = Cut(srcLines[srcL]+pos, width, fmtCode);
  772.             if (width & 16384)
  773.                 return MAX_LINES+1;
  774.             if (width & 32768) {
  775.                 broken = TRUE;
  776.                 width &= ~32768;
  777.             }
  778.             if (nOfDstL < MAX_LINES) {
  779.                 memcpy(dstLines[nOfDstL], srcLines[srcL]+pos, width);
  780.                 dstLines[nOfDstL][width] = broken ? '-' : '\0';
  781.                 dstLines[nOfDstL][width+1] = '\0';
  782. /*                printf("l=%d, dst=%s\n", nOfDstL, dstLines[nOfDstL]);
  783.             } else {
  784.                 printf("l=%d\n", nOfDstL);*/
  785.             }
  786.             nOfDstL++;
  787.             pos += width;
  788.             if (IsSpace(srcLines[srcL][pos]))
  789.                 pos++;
  790.         }
  791.         srcL++;
  792.     }
  793.     return nOfDstL;
  794. }
  795.